home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / ATARI_TN.C < prev    next >
C/C++ Source or Header  |  1990-05-11  |  8KB  |  355 lines

  1. /* Support routines for TNC2 emulator - Atari ST version */
  2.  
  3. #ifdef MWC
  4. #include <osbind.h>            /* os interface defines */
  5. #endif
  6. #include "global.h"
  7. #include "ax25.h"
  8. #include "timer.h"
  9. #include "slip.h"
  10. #include "tnc2.h"
  11.  
  12. #define     PIPEBUF    512            /* size of a pipe buffer */
  13. #define     FLOW_LOW    64            /* low-water mark */
  14. #define     FLOW_HIGH    480            /* high-water mark */
  15.  
  16. #define     SYSBASE    *((long *) 0x4f2L)    /* start of operating system */
  17.  
  18. static unsigned int biosvers;            /* set to BIOS version# */
  19.  
  20. #define     BCONSTAT    ((long (**)()) 0x51e)    /* Bconstat vector */
  21. #define     BCONIN        ((long (**)()) 0x53e)    /* Bconin vector */
  22. #define     BCOSTAT    ((long (**)()) 0x55e)    /* Bcostat vector */
  23. #define     BCONOUT    ((void (**)()) 0x57e)    /* Bconout vector */
  24.  
  25. extern char nospace[];
  26.  
  27. /* routines that simulate a character device to the client */
  28.  
  29. static struct tnc *dev2tnc[8];            /* tnc struct per device */
  30.  
  31. static long
  32. pconstat (dev)
  33.     int dev;
  34.  
  35. {
  36.     if (dev2tnc[dev]->output.num != 0)
  37.     return -1;
  38.  
  39.     return 0;
  40. }
  41.  
  42. static long
  43. pconin (dev)
  44.     int dev;
  45.  
  46. {
  47.     register struct tnc *tnc2;
  48.     char c;
  49.  
  50.     tnc2 = dev2tnc[dev];
  51.  
  52.     if (tnc2->output.num == 0)
  53.     return TCH_NOCHAR;        /* that will fail, but cannot wait */
  54.  
  55.     c = *tnc2->output.out++;
  56.     if (tnc2->output.out == tnc2->output.end)
  57.     tnc2->output.out = tnc2->output.begin;
  58.     if (--(tnc2->output.num) < FLOW_LOW)
  59.     tnc2->status &= ~TS_TXSTOP;
  60.  
  61.     return uchar(c);
  62. }
  63.  
  64. static long
  65. pcostat (dev)
  66.     int dev;
  67.  
  68. {
  69.     register struct tnc *tnc2;
  70.  
  71.     tnc2 = dev2tnc[dev];
  72.  
  73.     if (tnc2->input.num != 0 &&            /* something buffered? */
  74.     !(tnc2->status & TS_TXBUF))        /* not allowed to buffer? */
  75.     return 0;                /* buffer full */
  76.  
  77.     if (tnc2->input.num < FLOW_LOW ||        /* below flow control treshold? */
  78.     (!(tnc2->status & TS_RXSTOP) && tnc2->input.num < FLOW_HIGH))
  79.     return -1;                /* buffer is not full */
  80.  
  81.     return 0;                    /* buffer full */
  82. }
  83.  
  84. static void
  85. pconout (dev,c)
  86.     int dev,c;
  87.  
  88. {
  89.     register struct tnc *tnc2;
  90.  
  91.     tnc2 = dev2tnc[dev];
  92.  
  93.     if (tnc2->input.num == PIPEBUF)        /* buffer full? */
  94.     tnc2->status |= TS_RXOVR;        /* then we have an overrun */
  95.     else {
  96.     *tnc2->input.in++ = c;
  97.     if (tnc2->input.in == tnc2->input.end)
  98.         tnc2->input.in = tnc2->input.begin;
  99.     if (++(tnc2->input.num) >= FLOW_HIGH)
  100.         tnc2->status |= TS_RXSTOP;
  101.     }
  102. }
  103.  
  104. /* public routines for use by tnc2 emulator */
  105. /* initialize TNC2 client port */
  106. int
  107. tnc2_init (tnc2)
  108. register struct tnc *tnc2;
  109.  
  110. {
  111.     long sav_ssp;
  112.     char *sysbase;
  113.  
  114.     tnc2->status = 0;                /* Unbuffered, all OFF */
  115.  
  116.     sav_ssp = Super(NULL);            /* access system data */
  117.     sysbase = (char *) SYSBASE;            /* find OS */
  118.     biosvers = *((unsigned int *) (sysbase + 2)); /* read BIOS version */
  119.     Super(sav_ssp);
  120.  
  121.     switch (tnc2->dev)
  122.     {
  123.     case 0:
  124.     case 1:
  125.     case 3:
  126.     case 6:
  127.     case 7:
  128.     if (biosvers < 0x0102){
  129.         printf("devices 0-7 need BIOS 1.2 (Blitter-TOS)\n");
  130.         return 1;
  131.     }
  132.  
  133.     if ((tnc2->input.begin = malloc(PIPEBUF)) == NULLCHAR){
  134.         printf(nospace);
  135.         return 1;
  136.     }
  137.     tnc2->input.in = tnc2->input.out = tnc2->input.begin;
  138.     tnc2->input.end = tnc2->input.begin + PIPEBUF;
  139.     tnc2->input.num = 0;
  140.  
  141.     if ((tnc2->output.begin = malloc(PIPEBUF)) == NULLCHAR){
  142.         free(tnc2->input.begin);
  143.         printf(nospace);
  144.         return 1;
  145.     }
  146.     tnc2->output.in = tnc2->output.out = tnc2->output.begin;
  147.     tnc2->output.end = tnc2->output.begin + PIPEBUF;
  148.     tnc2->output.num = 0;
  149.  
  150.     dev2tnc[tnc2->dev] = tnc2;
  151.     sav_ssp = Super(NULL);            /* access system data */
  152.     tnc2->save_vec[0] = BCONSTAT[tnc2->dev]; /* save old handlers */
  153.     tnc2->save_vec[1] = BCONIN[tnc2->dev];
  154.     tnc2->save_vec[2] = BCOSTAT[tnc2->dev];
  155.     tnc2->save_vec[3] = BCONOUT[tnc2->dev];
  156.     BCONSTAT[tnc2->dev] = pconstat;        /* set new handlers */
  157.     BCONIN[tnc2->dev] = pconin;
  158.     BCOSTAT[tnc2->dev] = pcostat;
  159.     BCONOUT[tnc2->dev] = pconout;
  160.     Super(sav_ssp);
  161.     break;
  162.  
  163.     case 8:
  164.     Rsconf(1,0,0x88,0x01,0x01,0);        /* 9600 baud, 8 bits, no parity */
  165.     break;
  166.  
  167.     case 9:
  168.     sav_ssp = Super(NULL);            /* access MIDI chip */
  169.     *((char *) 0xfffffc04L) = 0x03;        /* RESET it */
  170.     *((char *) 0xfffffc04L) = 0x96;        /* set 7812.5/9600 baud */
  171.     Super(sav_ssp);
  172.     break;
  173.  
  174.     default:
  175.     printf("tnc2: unsupported device %d\n",tnc2->dev);
  176.     return 1;
  177.     }
  178.     return 0;
  179. }
  180.  
  181. /* terminate TNC2 client port */
  182. void
  183. tnc2_term (tnc2)
  184. register struct tnc *tnc2;
  185.  
  186. {
  187.     long sav_ssp;
  188.  
  189.     switch (tnc2->dev)
  190.     {
  191.     case 0:
  192.     case 1:
  193.     case 3:
  194.     case 6:
  195.     case 7:
  196.     sav_ssp = Super(NULL);            /* access system data */
  197.     BCONSTAT[tnc2->dev] = tnc2->save_vec[0]; /* restore old handlers */
  198.     BCONIN[tnc2->dev] = tnc2->save_vec[1];
  199.     BCOSTAT[tnc2->dev] = tnc2->save_vec[2];
  200.     BCONOUT[tnc2->dev] = tnc2->save_vec[3];
  201.     Super(sav_ssp);
  202.     dev2tnc[tnc2->dev] = NULLTNC;
  203.     free(tnc2->input.begin);
  204.     free(tnc2->output.begin);
  205.     break;
  206.     }
  207. }
  208.  
  209. /* read character from client, return -1 if none ready    */
  210. int
  211. tnc2_ichar (tnc2)
  212. register struct tnc *tnc2;
  213.  
  214. {
  215.     char c;
  216.  
  217.     switch (tnc2->dev)
  218.     {
  219.     case 0:
  220.     case 1:
  221.     case 3:
  222.     case 6:
  223.     case 7:
  224.     if (tnc2->status & TS_BREAK) {        /* received a BREAK */
  225.         tnc2->status &= ~TS_BREAK;
  226.         return TCH_BREAK;
  227.     }
  228.  
  229.     if (tnc2->input.num == 0)        /* nothing in buffer? */
  230.         return TCH_NOCHAR;
  231.  
  232.     c = *tnc2->input.out++;
  233.     if (tnc2->input.out == tnc2->input.end)
  234.         tnc2->input.out = tnc2->input.begin;
  235.     if (--(tnc2->input.num) < FLOW_LOW)
  236.         tnc2->status &= ~TS_RXSTOP;
  237.  
  238.     return uchar(c);
  239.  
  240.     case 8:
  241.     if (!Bconstat(1))        /* check RS232 (AUX) status */
  242.         break;
  243.  
  244.     return uchar(Bconin(1));    /* read char from RS232 (AUX) */
  245.  
  246.     case 9:
  247.     if (!Bconstat(3))        /* check MIDI status */
  248.         break;
  249.  
  250.     return uchar(Bconin(3));    /* read char from MIDI */
  251.     }
  252.  
  253.     return TCH_NOCHAR;
  254. }
  255.  
  256. /* send character to client, return 0 when blocked */
  257. /* when character is <0, only check if it is blocked */
  258. int
  259. tnc2_ochar (tnc2,c)
  260. register struct tnc *tnc2;
  261. int c;
  262.  
  263. {
  264.     int i;
  265.  
  266.     switch (tnc2->dev)
  267.     {
  268.     case 0:
  269.     case 1:
  270.     case 3:
  271.     case 6:
  272.     case 7:
  273.     if (c < 0) {            /* a status check */
  274.         if (tnc2->output.num < FLOW_LOW)
  275.         return 1;
  276.  
  277.         /* maybe we better be conservative and don't allow him to go...
  278.         if (!(tnc2->status & TS_TXSTOP) && tnc2->output.num < FLOW_HIGH)
  279.         return 1;   (he will try again later!) */
  280.  
  281.         return 0;
  282.     }
  283.  
  284.     if (tnc2->output.num == PIPEBUF) {    /* buffer full? */
  285.         eihalt();                /* give a chance to read chars */
  286.         if (tnc2->output.num == PIPEBUF) {    /* still no space? */
  287.         tnc2->status |= TS_TXOVR;    /* transmitter overrun */
  288.         return 0;
  289.         }
  290.     }
  291.  
  292.     *tnc2->output.in++ = c;
  293.     if (tnc2->output.in == tnc2->output.end)
  294.         tnc2->output.in = tnc2->output.begin;
  295.     if (++(tnc2->output.num) >= FLOW_HIGH)
  296.         tnc2->status |= TS_TXSTOP;
  297.  
  298.     return 1;
  299.  
  300.     case 8:
  301.     i = 50;
  302.  
  303.     while (!Bcostat(1) && --i)    /* when output buffer is full */
  304.         eihalt();            /* wait a short while */
  305.  
  306.     if (i == 0)            /* tried it, but still not ready */
  307.         break;
  308.  
  309.     if (c >= 0)
  310.         Bconout(1,c);        /* send char to RS232 (AUX) */
  311.  
  312.     return 1;
  313.  
  314.     case 9:
  315.     if (c >= 0)
  316.         Bconout(3,c);        /* send char to MIDI */
  317.  
  318.     return 1;
  319.     }
  320.  
  321.     tnc2->status |= TS_TXOVR;        /* transmitter overrun */
  322.     return 0;
  323. }
  324.  
  325. /* set flowcontrol method for specified client */
  326. /* method 1=soft (XON/XOFF) 2=hard (RTS/CTS) */
  327. void
  328. tnc2_flow (tnc2,method)
  329. register struct tnc *tnc2;
  330. int method;
  331.  
  332. {
  333.     switch (tnc2->dev)
  334.     {
  335.     case 0:
  336.     case 1:
  337.     case 3:
  338.     case 6:
  339.     case 7:
  340.     if (method & 1)            /* soft control used to set TX buffer */
  341.         tnc2->status |= TS_TXBUF;
  342.     else
  343.         tnc2->status &= ~TS_TXBUF;
  344.  
  345.     break;
  346.  
  347.     case 8:
  348.     if (biosvers < 0x0102)        /* when using old BIOS */
  349.         method &= ~2;        /* hardware flowctrl does not work */
  350.  
  351.     Rsconf(-1,method,-1,-1,-1,-1);    /* set RS232 flow control method */
  352.     break;
  353.     }
  354. }
  355.